IMPLEMENTATION MODULE Tad_ControlEstudio;

FROM libc IMPORT exit, printf;
FROM MathLib0 IMPORT sqrt;
FROM FpuIO IMPORT WriteReal;
FROM StrIO IMPORT WriteString, WriteLn;
FROM Scan IMPORT OpenSource;
FROM NumberIO IMPORT ReadInt,WriteInt;
FROM FIO IMPORT OpenToRead,File,EOF,ReadString,Close;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;
FROM DynamicStrings IMPORT String, Slice, CopyOut, Index, InitString;
FROM StringConvert IMPORT StringToInteger;
FROM Tad_CargaDatos IMPORT Carga_Lineas,CargaLinea;
IMPORT Tad_Lista;
IMPORT Tad_Estudiante;
IMPORT Tad_Materia;
IMPORT Tad_Profesor;
IMPORT Tad_Nota;
IMPORT Tad_Par;
IMPORT Tad_Curso;
IMPORT Tad_Solicitud;
IMPORT Tad_ArbolBinomial;



PROCEDURE Carga_Archivo (data : File; VAR x:Tad_Lista.Lista; VAR y:Tad_Lista.Lista; VAR z:Tad_Lista.Lista; VAR w:Tad_Lista.Lista);
VAR n,m,o,p: INTEGER;
VAR verificar: BOOLEAN;
VAR i: CARDINAL;

BEGIN
	Carga_Lineas(n,m,o,p,data);
	
	FOR i:= 0 TO n-1 DO
		verificar := Tad_Lista.Lista_Agregar(x,Tad_Estudiante.Carga(data));
		IF NOT verificar THEN
			WriteLn();
			WriteString('la carga del archivo de los estudiantes a fallado');
			WriteLn();
		END;
	END;
	FOR i:= 0 TO m-1 DO
		verificar := Tad_Lista.Lista_Agregar (y,Tad_Materia.Carga(data));
		IF NOT verificar THEN
			WriteLn();
			WriteString('la carga del archivo de las materias a fallado');
			WriteLn();
		END;
	END;
	
	FOR i:= 0 TO o-1 DO
		verificar := Tad_Lista.Lista_Agregar (z,Tad_Profesor.Carga(data));
		IF NOT verificar THEN
			WriteLn();
			WriteString('la carga del archivo de los Profesores a fallado');
			WriteLn();
		END;
	END;
	
	FOR i:= 0 TO p-1 DO
		verificar := Tad_Lista.Lista_Agregar (w,Tad_Nota.Carga(data));
		IF NOT verificar THEN
			WriteLn();
			WriteString('la carga del archivo de las notas a fallado');
			WriteLn();
		END;
	END;

END Carga_Archivo;


PROCEDURE Creditos (VAR asignaturas: Tad_Lista.Lista; codigo: INTEGER) : INTEGER;
VAR i : CARDINAL;
VAR cod_materia : INTEGER ;
VAR materia : Tad_Materia.Materia;
  BEGIN
	FOR i := 0 TO 7 DO;
		materia := Tad_Lista.Lista_Obtener(asignaturas,i);
		cod_materia := Tad_Materia.GetCodigo(materia);		
		IF  cod_materia = codigo THEN
			RETURN Tad_Materia.GetCreditos(materia);	
		END;
	END;
	RETURN 0;
  END Creditos; 

(*******************************************************************************
   Funcion: Reporte_Indices
   Descripcion: Imprime en pantalla la información de todos los estudiantes con 
   sus índices.
   Parametros: x:Arr_notas; y:Arr_estudiantes; z:Arr_materias; M:CARDINAL; N:CARDINAL; P:CARDINAL
   Precondicion: Datos de las notas, estudiantes y materias cargados anteriormente del archivo texto
   Postcondicion: calcula el indice de cada estudiante y lo almacena de la variable 'indice',
   muestra en pantalla el codigo de los estudiantes, nombres de los estudiantes y sus indices
 *******************************************************************************)

PROCEDURE Reporte_Indices(x: Tad_Lista.Lista (*Notas*); y: Tad_Lista.Lista (*Estudiantes*); z: Tad_Lista.Lista (*Materias*));
VAR indice:REAL;
VAR creditos,suma,suma_creditos,k:INTEGER;
VAR i,j: CARDINAL;
VAR tamx, tamy:CARDINAL ;
VAR nota : Tad_Nota.Nota;
VAR estudiante : Tad_Estudiante.Estudiante;
  BEGIN
	i := 0;
	tamy := Tad_Lista.Lista_Tamanio(y);
	tamx :=  Tad_Lista.Lista_Tamanio(x);
	(*Recorriendo estudiantes*)
	WHILE i < tamy DO
	  suma := 0;
	  suma_creditos := 0;
	  indice := 0.0;
	  j :=0;
	  (*Recorriendo notas del estudiante*)
	  WHILE j < tamx DO		
		nota := Tad_Lista.Lista_Obtener(x,j);
		estudiante := Tad_Lista.Lista_Obtener(y,i);
		IF  (Tad_Estudiante.GetCodigo(estudiante) = 
			Tad_Nota.GetCodigoEstudiante(nota)) THEN
			creditos := Creditos(z,Tad_Nota.GetCodigoMateria(nota));
			suma := suma + Tad_Nota.GetNota(nota)*creditos;
			suma_creditos := suma_creditos + creditos;
		END;
		j := j + 1;
	  END;
		IF suma_creditos > 0 THEN
			indice := FLOAT(suma)/FLOAT(suma_creditos);
			estudiante := Tad_Lista.Lista_Obtener(y,i);
			WriteLn();
			WriteInt(Tad_Estudiante.GetCodigo(estudiante),0);
			WriteString('   ');
			Tad_Estudiante.ImprimirNombre(estudiante);
			WriteString('   ');
			WriteReal(indice,4,4);
			WriteLn();
		END;
	 	IF suma_creditos = 0 THEN
			estudiante := Tad_Lista.Lista_Obtener(y,i);
			WriteLn();
			WriteInt(Tad_Estudiante.GetCodigo(estudiante),0);
			WriteString('   ');
			Tad_Estudiante.ImprimirNombre(estudiante);
			WriteString('   ');
			WriteString("0,0");
			WriteLn();
		END;
	  i:= i+1;
	END;
  END Reporte_Indices;	
  
  	
(*******************************************************************************
   Funcion: Reporte_Mejores
   Descripcion: Imprime en pantalla la información de todos los estudiantes con 
   índices mayores a indice_menor
   Parametros: x:Arr_notas; y:Arr_estudiantes; z:Arr_materias; indice_menor:REAL;
   M:CARDINAL; N:CARDINAL; P:CARDINAL
   Precondicion: Datos de las notas, estudiantes y materias cargados anteriormente 
   del archivo texto.
   Postcondicion: calcula el indice de cada estudiante y lo almacena de la variable
   'indice', muestra en pantalla el codigo de los estudiantes, nombres de los 
   estudiantes y sus indices que esten por encima de la variable indice_menor
 *******************************************************************************)

PROCEDURE Reporte_Mejores(x: Tad_Lista.Lista(*Notas*); y: Tad_Lista.Lista(*Estudiantes*); z: Tad_Lista.Lista(*Materias*); indice_menor:REAL);
VAR indice:REAL;
VAR creditos,suma,suma_creditos,k:INTEGER;
VAR i,j: CARDINAL;
VAR tamx, tamy:CARDINAL ;
VAR nota: Tad_Nota.Nota;
VAR estudiante: Tad_Estudiante.Estudiante;
BEGIN
	i := 0;
	tamy := Tad_Lista.Lista_Tamanio(y);
	tamx :=  Tad_Lista.Lista_Tamanio(x);
	(*Recorriendo estudiantes*)
	WHILE i < tamy DO
		suma := 0;
		suma_creditos := 0;
		indice := 0.0;
		j :=0;
		(*Recorriendo notas del estudiante*)
		WHILE j < tamx DO		
			nota := Tad_Lista.Lista_Obtener(x,j);
			estudiante := Tad_Lista.Lista_Obtener(y,i);
			IF  (Tad_Estudiante.GetCodigo(estudiante) = 
				Tad_Nota.GetCodigoEstudiante(nota)) THEN
				creditos := Creditos(z,Tad_Nota.GetCodigoMateria(nota));
				suma := suma + Tad_Nota.GetNota(nota)*creditos;
				suma_creditos := suma_creditos + creditos;
			END;
			j := j + 1;
		END;
		IF suma_creditos > 0 THEN
			indice := FLOAT(suma)/FLOAT(suma_creditos);
			IF indice > indice_menor THEN
				estudiante := Tad_Lista.Lista_Obtener(y,i);
				WriteLn();
				WriteInt(Tad_Estudiante.GetCodigo(estudiante),0);
				WriteString('   ');
				Tad_Estudiante.ImprimirNombre(estudiante);
				WriteString('   ');
				WriteReal(indice,4,4);
				WriteLn();
			END;
		END;
	  i:= i+1;
	END;
  END Reporte_Mejores;
  
(*******************************************************************************
   Funcion: Relacion_Materia
   Descripcion: calcula la cantidad de aprobados y reprobados de estudiantes en 
   una materia específica
   Parametros: x:Arr_notas; y:Arr_materias; cod_materia:INTEGER; M:CARDINAL; P:CARDINAL
   Precondicion: los datos de notas y materias cargados anteriormente
   Postcondicion: imprime la cantidad de aprobados y reprobados en una materia 
   junto con el nombre de la misma.
 *******************************************************************************)
  
PROCEDURE Relacion_Materia(x:Tad_Lista.Lista (*Notas*); cod_materia:INTEGER);

VAR aprobados,reprobados:INTEGER;
VAR i , tamx: CARDINAL;
VAR nota : Tad_Nota.Nota;
  BEGIN
	aprobados := 0;
	reprobados := 0;
	i:=0;
	tamx := Tad_Lista.Lista_Tamanio(x);
	WHILE i < tamx DO
		nota := Tad_Lista.Lista_Obtener(x,i);
		IF Tad_Nota.GetCodigoMateria(nota) = cod_materia THEN
			IF Tad_Nota.GetNota(nota) >= 3 THEN
				aprobados := aprobados + 1;
			ELSE
				reprobados := reprobados + 1;
			END;
		END;
		i := i+1;
	END;
	
	
	WriteLn();
	WriteString('La relación de aprobados/reprobados en la materia seleccionada es de:');
	WriteInt(aprobados,0);
	WriteString('/');
	WriteInt(reprobados,0);
	WriteLn();
	
  END Relacion_Materia;

(*******************************************************************************
   Funcion: Relacion_Profesor
   Descripcion: calcula la cantidad de aprobados y reprobados de estudiantes con un profesor en específico
   Parametros: x:Arr_notas; y:Arr_profesores; cod_profesor:INTEGER; O:CARDINAL; P:CARDINAL
   Precondicion: Datos de Notas y Profesores cargados anteriormente
   Postcondicion: imprime la cantidad de aprobados y reprobados con respecto a un profesor y el nombre del mismo.
 *******************************************************************************)

PROCEDURE Relacion_Profesor(x: Tad_Lista.Lista(*Notas*); cod_profesor:INTEGER);
  
VAR aprobados,reprobados : INTEGER;
VAR i, tamx : CARDINAL;
VAR nota: Tad_Nota.Nota;

  BEGIN
	aprobados := 0;
	reprobados := 0;
	i:=0;
	tamx := Tad_Lista.Lista_Tamanio(x);
	WHILE i<tamx DO
		nota := Tad_Lista.Lista_Obtener(x,i);
		IF Tad_Nota.GetCodigoProfesor(nota) = cod_profesor THEN
			IF Tad_Nota.GetCodigoProfesor(nota) >= 3 THEN
				aprobados := aprobados + 1;
			ELSE
				reprobados := reprobados + 1;
			END;
		END;
		i := i+1;
	END;
	
	WriteLn();
	WriteString('La relación de aprobados/reprobados del profesor seleccionado es de:');
	WriteInt(aprobados,0);
	WriteString('/');
	WriteInt(reprobados,0);
	WriteLn();
	
  END Relacion_Profesor;
  (*
PROCEDURE Comparar(profesores1:Tad_Lista.Lista; profesores2:Tad_Lista.Lista; O1:INTEGER; O2:INTEGER);
VAR i,j:CARDINAL;

  BEGIN
  WriteString('1111111');
	FOR i:= 0 TO O1-1 DO
		WriteString('222222');
		FOR j:= 0 TO O2-1 DO
			IF (Tad_Profesor.GetCodigo(Tad_T.GetProfesor(Tad_Lista.Lista_Obtener(profesores1,i))) = 
				Tad_Profesor.GetCodigo(Tad_T.GetProfesor(Tad_Lista.Lista_Obtener(profesores2,j)))) THEN
				WriteLn();
				WriteString('los profesores que trabajan en ambas universidades son: ');
				WriteLn();
				WriteString('Codigo: ');
				WriteInt(Tad_Profesor.GetCodigo(Tad_T.GetProfesor(Tad_Lista.Lista_Obtener(profesores1,i))),0);
				WriteString('.  Nombre: ');
				Tad_Profesor.ImprimirNombre((Tad_T.GetProfesor(Tad_Lista.Lista_Obtener(profesores1,i))));
				WriteLn();
				WriteString('333333');
			END;
		END;
	END;
  END Comparar;*)
  
END Tad_ControlEstudio.
